// Normal Block:

// // Genesis Block:
// // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
// //   CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
// //     CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
// //     CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
// //   vMerkleTree: 4a5e1e

// // Genesis block
// block.nVersion = 1;
// block.nTime = 1231006505;
// block.nBits = 0x1d00ffff;
// block.nNonce = 2083236893;

// Genesis Block:

use crate::transaction;
use bc_base::{
    BlockId,
    block::{self, Block},
    transaction::Transaction,
};

pub fn create_genesis_block() -> (BlockId, Block, Transaction) {
    let header = block::create_block_header_for_genesis_block();
    let mut block = Block::new(header);

    let tx = transaction::create_coinbase_for_genesis_block();
    // let tx_id = tx.calc_tx_id();
    block.add_transaction(tx.clone());

    let merkle_root_hash = block.build_merkle_tree().unwrap();
    block.set_merkle_root(merkle_root_hash);
    let block_id = block.find_and_set_valid_nonce();

    (block_id, block, tx)
}

// #[cfg(test)]
use bc_base::{PublicKeyHashBytes, TransactionValue};

// #[cfg(test)]
fn create_tx_for_test(
    pub_key_hash_miner: &PublicKeyHashBytes,
    value: TransactionValue,
) -> Transaction {
    let tx_in = transaction::create_transaction_in_for_coinbase(0, 1);
    let tx_out = transaction::create_transaction_out(pub_key_hash_miner, value);
    let inputs = vec![tx_in];
    let outputs = vec![tx_out];
    transaction::create_transaction(inputs, outputs)
}

// #[cfg(test)]
pub fn create_block_for_test(
    pub_key_hash_miner: &PublicKeyHashBytes,
    value: TransactionValue,
    nbits: u32,
) -> (BlockId, Block, Transaction) {
    let header = block::create_block_header_for_test(nbits);
    let mut block = Block::new(header);
    let tx = create_tx_for_test(pub_key_hash_miner, value);

    block.add_transaction(tx.clone());

    let merkle_root_hash = block.build_merkle_tree().unwrap();
    block.set_merkle_root(merkle_root_hash);
    let block_id = block.find_and_set_valid_nonce();

    (block_id, block, tx)
}

#[cfg(test)]
mod tests {
    use super::*;
    use bc_base::block::BlockHeader;

    #[test]
    fn test_block_serialize_len() {
        let header_len = std::mem::size_of::<BlockHeader>();
        let usize_len = std::mem::size_of::<usize>();

        let mut block = Block::new_null();
        assert_eq!(block.serialize().len(), header_len + usize_len);

        let tx = crate::transaction::create_coinbase_for_genesis_block();
        let tx_len = tx.serialize().len();
        block.add_transaction(tx.clone());
        assert_eq!(block.serialize().len(), header_len + usize_len + tx_len);
        block.add_transaction(tx);
        assert_eq!(block.serialize().len(), header_len + usize_len + tx_len * 2);
    }
}
